﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;

namespace LowLevelGraphics.Filter
{
    /// <summary>
    /// B = ordfilt2(A, order, domain) replaces each element in A by the orderth element
    /// in the sorted set of neighbors specified by the nonzero elements in domain.
    /// B = ordfilt2(A, order, domain, S) where S is the same size as domain, 
    /// uses the values of S corresponding to the nonzero values of domain as additive offsets.
    /// B = ordfilt2(..., padopt) controls how the matrix boundaries are padded. 
    /// Set padopt to 'zeros' (the default) or 'symmetric'. If padopt is 'zeros', 
    /// A is padded with 0's at the boundaries. If padopt is 'symmetric', 
    /// A is symmetrically extended at the boundaries.
    /// </summary>
    public class ordfilter2 : BaseImageFilter
    {
        protected int m_nOrderedIndex = 1;

        /// <summary>
        /// Initializes a new instance of the <see cref="ordfilter2"/> class.
        /// </summary>
        public ordfilter2()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="ordfilter2"/> class.
        /// </summary>
        /// <param name="_ordfilter2">The _ordfilter2.</param>
        internal ordfilter2(ordfilter2 _ordfilter2)
        {
            m_nOrderedIndex = _ordfilter2.m_nOrderedIndex;
        }

        /// <summary>
        /// Gets or sets the index of the ordered.
        /// </summary>
        /// <value>The index of the ordered.</value>
        public int OrderedIndex
        {
            get { return m_nOrderedIndex; }
            set { m_nOrderedIndex = value; }
        }

        /// <summary>
        /// Execute this Filter
        /// A Debug Statement is written if a concrete Filter is called
        /// </summary>
        /// <param name="_bitmap"></param>
        /// <returns></returns>
        public override UnsafeBitmap Execute(UnsafeBitmap _bitmap)
        {
            Color[,] aColorBitmap = _bitmap.GetAsPixelArrayColor();

            int nHeight = _bitmap.Height;
            int nWidth = _bitmap.Width;

            Color[] aColor = new Color[8];
            List<int> aIntColorValue = new List<int>(8);
            aIntColorValue.AddRange(new int[] { 0, 0, 0, 0, 0, 0, 0, 0 });

            List<Point> definitionsEnvironmentPointListClockwise = Definitions.EnvironmentPointListClockwise;

            int x = 0;
            int y = 0;
            int nValue = 0;
            int i = 0;
            for (y = 0; y < nHeight; y++)
            {
                for (x = 0; x < nWidth; x++)
                {
                    aColor = Segmentation.GetEnvironmentPixelColorArray(aColorBitmap, x, y, definitionsEnvironmentPointListClockwise, aColor);
                    for (i = 0; i < 8; i++)
                    {
                        nValue = aColor[i].ToArgb();
                        aIntColorValue[i] = nValue;
                    }
                    aIntColorValue.Sort();
                    _bitmap.SetPixel(x, y, Color.FromArgb(aIntColorValue[m_nOrderedIndex]));
                }
            }
            return _bitmap;
        }

        /// <summary>
        /// This is used to clone a filter, each filter must implement it's own clone functionality
        /// </summary>
        /// <returns></returns>
        public override object Clone()
        {
            return new ordfilter2(this);
        }
    }
}
